﻿using System;
using System.Diagnostics;

namespace Simp.Model.CoreExpressions.Sequences
{
	/// <summary>Encapsulates an expression selecting one element out of a sequence.</summary>
	[ExpressionName(ElementSelectorExpressionName)]
	[ParameterPolicy("source", "index")]
	[DebuggerDisplay("{ExpressionHelper.Serialize(this)}")]
	public class ElementSelectorExpression : IExpression, ISimplifiableExpression, IExpressionSerializer
	{
		/// <summary>Name of the expression.</summary>
		public const string ElementSelectorExpressionName = "SequenceElement";

		#region ISimplifiableExpression Members
		IExpression ISimplifiableExpression.Simplify(SimplificationMode simplificationMode, params IExpression[] parameterList)
		{
			if (parameterList == null)
			{
				throw new ArgumentNullException("parameterList");
			}
			if (parameterList.Length == 2)
			{
				IExpression sequence = parameterList[0];
				IExpression index = parameterList[1];
				ISequenceAccessor accessor = ExpressionHelper.GetAccessor(sequence);
				IntegerExpression indexInteger = index as IntegerExpression;

				if (accessor == null || indexInteger == null)
				{
					return null;
				}
				else
				{
					int count = accessor.Count;
					int indexValue = indexInteger.Value;

					if (indexValue >= count || indexValue < -count)
					{
						return null;
					}
					else
					{
						return accessor[indexValue >= 0 ? indexValue : count + indexValue];
					}
				}
			}
			else
			{
				return null;
			}
		}
		#endregion

		#region IExpressionSerializer Members
		void IExpressionSerializer.Serialize(AppendOnlyStringBuilder builder, params IExpression[] parameters)
		{
			if (builder == null)
			{
				throw new ArgumentNullException("builder");
			}
			if (parameters == null)
			{
				throw new ArgumentNullException("parameters");
			}
			if (parameters.Length == 2)
			{
				IExpression sequence = parameters[0];
				IExpression index = parameters[1];

				ExpressionHelper.Serialize(builder, sequence);
				builder.Append("[");
				ExpressionHelper.Serialize(builder, index);
				builder.Append("]");
			}
			else
			{
				ExpressionHelper.SerializeGeneric(builder, this, parameters);
			}
		}
		#endregion
	}
}